//////////////////////////////////////////////////////////////////////////////////////////////
//	File			:	"Emitter.cpp"
//
//	Author			:	Mike Davis, Matt Stover, James Thornton, Keith Webster
//	
//	Project			:	TacWars
//
//	Last Modified	:	11/6/2013
//
//	Purpose			:	
//
//////////////////////////////////////////////////////////////////////////////////////////////

#include "Emitter.h"
#include "../GameObjects/Entity.h"

#include <math.h>

Emitter::Emitter(string _name, int _particleTexture, EmitterType _eType, Entity* _following, int _scaleX, int _scaleY, 
				 int _posX, int _posY,	int _maxParticles, float _emissionRate, float _minLife, float _maxLife,
				 float _minSpeed, float _maxSpeed, float _emitDirX, float _emitDirY, float _minDir, float _maxDir,
				 int _minScaleX, int _minScaleY,	int _maxScaleX, int _maxScaleY, float _rotationRate,
				 D3DCOLOR _startColor, D3DCOLOR _finColor, bool _looping)
{
	name			= _name;
	partTextureId	= _particleTexture;
	eType			= _eType;
	following		= _following;
	emitScale.x		= _scaleX;
	emitScale.y		= _scaleY;
	emitPos.x		= _posX;
	emitPos.y		= _posY;
	maxParticles	= _maxParticles;
	emissionRate	= _emissionRate;
	minLife			= _minLife;
	maxLife			= _maxLife;
	minSpeed		= _minSpeed;
	maxSpeed		= _maxSpeed;
	emitDir.fX		= _emitDirX;
	emitDir.fY		= _emitDirY;
	minDir			= _minDir;
	maxDir			= _maxDir;
	minScale.fX		= _minScaleX;
	minScale.fY		= _minScaleY;
	maxScale.fX		= _maxScaleX;
	maxScale.fY		= _maxScaleY;
	rotationRate	= _rotationRate;
	startColor		= _startColor;
	finColor		= _finColor;
	isLooping		= _looping;
	timeSince		= 0;
}

void Emitter::Update(float dt)
{
	timeSince += dt;
	int particlesAlive =0;
	//Update current particles and find out
	//How many particles are alive?

	if(following)
	{
		emitPos.x = following->GetPosX();
		emitPos.y = following->GetPosY();
	}
	for (unsigned int i = 0; i < particles.size(); i++)
	{
		if((particles[i]->currLife -= dt) <=0)
		{
			particles[i]->isAlive = false;
			continue;
		}
		else
		{
			particlesAlive++;
			//Vector math for changing speed, and moving particle
			particles[i]->currSpeed += particles[i]->dSpeed*dt;
			tVector2D velVec = emitDir;
			velVec *= particles[i]->currSpeed;
			velVec = Vector2DRotate(velVec, particles[i]->partDir);
			particles[i]->currPos += velVec*dt;
			//Scale changing
			particles[i]->currScaleX += particles[i]->dScale.fX *dt;
			particles[i]->currScaleY += particles[i]->dScale.fY *dt;
			//Rotation
			particles[i]->currRotation += rotationRate*dt;

			//Color Blend
			particles[i]->currAlpha = particles[i]->currAlpha + float(particles[i]->dAlpha *dt);
			particles[i]->currRed = particles[i]->currRed + float(particles[i]->dRed *dt);
			particles[i]->currGreen = particles[i]->currGreen + float(particles[i]->dGreen *dt);
			particles[i]->currBlue = particles[i]->currBlue + float(particles[i]->dBlue *dt);
			particles[i]->currColor= D3DCOLOR_COLORVALUE(
				particles[i]->currRed,
				particles[i]->currGreen,
				particles[i]->currBlue,
				particles[i]->currAlpha				
				);
		}
	}

	//Emit new particles by emission rate, up to max
	if(particles.size() < maxParticles)
	{
		if(timeSince > (1/emissionRate))
		{
			for (float i = 0; i < fmod(timeSince , (1 / emissionRate)); i++)
			{
				Particle* add = new Particle();
				add->isAlive = true;
				add->currLife = (float)rand()/((float)RAND_MAX/(maxLife - minLife)) + minLife;
				// Based on Emitter Type
				switch(eType)
				{
				case DOT:
					add->currPos.fX = emitPos.x;
					add->currPos.fY = emitPos.y;
					break;
				case RECTANGLE:
					add->currPos.fX = rand()%((emitPos.x + emitScale.x)-emitPos.x) + emitPos.x;
					add->currPos.fY = rand()%((emitPos.y + emitScale.y)-emitPos.y) + emitPos.y;
					break;
				case CIRCLE:
					{
						int radius = emitScale.x/2;
						int emitCenX = emitPos.x + radius;
						int emitCenY = emitPos.y + radius;
						tVector2D placement;
						placement.fX = 0;
						placement.fY = rand()%radius;
						placement = Vector2DRotate(placement, (float)rand()/((float)RAND_MAX/(3.14159*2)));
						add->currPos.fX = emitCenX + placement.fX;
						add->currPos.fY = emitCenY + placement.fY;
						break;
					}
				case LINE:
					add->currPos.fX = rand()%((emitPos.x + emitScale.x)-emitPos.x) + emitPos.x;
					add->currPos.fY = emitPos.y;

				}
				////////////////////////
				add->currScaleX = minScale.fX;
				add->currScaleY = minScale.fY;
				add->dScale.fX = (maxScale.fX - minScale.fX)/add->currLife;
				add->dScale.fY = (maxScale.fY - minScale.fY)/add->currLife;
				add->dSpeed = (maxSpeed - minSpeed)/add->currLife;
				add->currSpeed = minSpeed;
				add->partDir = (float)rand()/((float)RAND_MAX/(maxDir - minDir)) + minDir;
				add->currRotation = 0;
				add->currColor = startColor;
				add->dAlpha =	((float(finColor >> 24)-float(startColor >> 24)) /255 )/add->currLife;
				add->dRed =		((float((finColor >> 16) & 0xFF)-float((startColor >> 16) & 0xFF)) / 255)/add->currLife;
				add->dGreen =	((float((finColor >> 8) & 0xFF)-float((startColor >> 8) & 0xFF)) / 255)/add->currLife;
				add->dBlue =	float(((finColor & 0xFF)-(startColor & 0xFF)) / add->currLife)/255.0f;
				float testa = ((float((finColor >> 16) & 0xFF)-float((startColor >> 16) & 0xFF)) / 255);
				int testfa = finColor>>24;
				int testsa = startColor>>24;
				add->currAlpha =	(add->currColor >> 24)/255;
				add->currRed =		((add->currColor >> 16) & 0xFF)/255;
				add->currGreen =	((add->currColor >> 8) & 0xFF)/255;
				add->currBlue =		(add->currColor & 0xFF)/255;

				particles.push_back(add);
			}
			timeSince = 0;

		}
	}
	//If max particles are achieved, revive old ones
	//Random burst?//////////////////////////////////////////
	else if(isLooping)
	{
		if(timeSince > (1/emissionRate))
		{
			for (float i = 0; i < fmod(timeSince , (1 / emissionRate)); i++)
			{
				for (int j = 0; j < maxParticles; j++)
				{
					if(!particles[j]->isAlive)
					{
						particles[j]->isAlive = true;
						particles[j]->currLife = (float)rand()/((float)RAND_MAX/(maxLife - minLife)) + minLife;
						// Based on Emitter Type
						switch(eType)
						{
						case DOT:
							particles[j]->currPos.fX = emitPos.x;
							particles[j]->currPos.fY = emitPos.y;
							break;
						case RECTANGLE:
							particles[j]->currPos.fX = rand()%((emitPos.x + emitScale.x)-emitPos.x) + emitPos.x;
							particles[j]->currPos.fY = rand()%((emitPos.y + emitScale.y)-emitPos.y) + emitPos.y;
							break;
						case CIRCLE:
							{
								//TODO
								int radius = emitScale.x/2;
								int emitCenX = emitPos.x + radius;
								int emitCenY = emitPos.y + radius;
								tVector2D placement;
								placement.fX = 0;
								placement.fY = rand()%radius;
								placement = Vector2DRotate(placement, (float)rand()/((float)RAND_MAX/(3.14159*2)));
								particles[j]->currPos.fX = emitCenX + placement.fX;
								particles[j]->currPos.fY = emitCenY + placement.fY;
								break;
							}
						case LINE:
							particles[j]->currPos.fX = rand()%((emitPos.x + emitScale.x)-emitPos.x) + emitPos.x;
							particles[j]->currPos.fY = emitPos.y;

						}
						////////////////////////
						particles[j]->currScaleX = minScale.fX;
						particles[j]->currScaleY = minScale.fY;
						particles[j]->dScale.fX = (maxScale.fX - minScale.fX)/particles[j]->currLife;
						particles[j]->dScale.fY = (maxScale.fY - minScale.fY)/particles[j]->currLife;
						particles[j]->dSpeed = (maxSpeed - minSpeed)/particles[j]->currLife;
						particles[j]->currSpeed = minSpeed;
						particles[j]->partDir = (float)rand()/((float)RAND_MAX/(maxDir - minDir)) + minDir; 
						particles[j]->currRotation = 0;
						particles[j]->currColor = startColor;
						particles[j]->dAlpha =	((float(finColor >> 24)-float(startColor >> 24)) /255 )/particles[j]->currLife;
						particles[j]->dRed =		((float((finColor >> 16) & 0xFF)-float((startColor >> 16) & 0xFF)) / 255)/particles[j]->currLife;
						particles[j]->dGreen =	((float((finColor >> 8) & 0xFF)-float((startColor >> 8) & 0xFF)) / 255)/particles[j]->currLife;
						particles[j]->dBlue =	float(((finColor & 0xFF)-(startColor & 0xFF)) / particles[j]->currLife)/255.0f;
						particles[j]->currAlpha =	(particles[j]->currColor >> 24)/255;
						particles[j]->currRed =		((particles[j]->currColor >> 16) & 0xFF)/255;
						particles[j]->currGreen =	((particles[j]->currColor >> 8) & 0xFF)/255;
						particles[j]->currBlue =	(particles[j]->currColor & 0xFF)/255;

						timeSince = 0;
						break;
					}

				}
			}
		}

	}


}

void Emitter::Render()
{
	pTM = CSGD_TextureManager::GetInstance();
	RECT rSource = {0,0, pTM->GetTextureWidth(partTextureId), pTM->GetTextureHeight(partTextureId)};
	for (unsigned int i = 0; i < particles.size(); i++)
	{
		if(particles[i]->isAlive)
		{
			pTM->Draw(partTextureId, (int)particles[i]->currPos.fX - (int)((float)pTM->GetTextureWidth(partTextureId) / 2) * particles[i]->currScaleX, 
				(int)particles[i]->currPos.fY - (int)((float)pTM->GetTextureHeight(partTextureId) / 2) * particles[i]->currScaleY,
				float(particles[i]->currScaleX), float(particles[i]->currScaleY), &rSource, 
				16.0f,16.0f, particles[i]->currRotation, particles[i]->currColor);
		}

	}
}
